﻿using System.Collections.Generic;
using MVVM_CAD.Model;

namespace MVVM_CAD.Algorithms
{
    public class SchornFisherPolygonConvexity
    {
        public static bool IsConvex(IPoint[] polygonVertices)
        {
            var mask = 0;
            var n = polygonVertices.Length;
            for (var i = 0; i < n; ++i)
            {
                var j = (i + 1) % n;
                var k = (i + 2) % n;
                double z = Ccw(polygonVertices[i], polygonVertices[j], polygonVertices[k]);
                if (z < 0)
                {
                    mask |= 1;
                }
                else if (z > 0)
                {
                    mask |= 2;
                }
                if (mask == 3)
                {
                    return false;
                }
            }
            return !HasCrossedLines(polygonVertices);
        }

        /**
         * Respondemos si existen lineas en el poligono que se crucen
         */
        public static bool HasCrossedLines(IPoint[] polygonVertices)
        {
            if (polygonVertices.Length <= 3)
            {
                return false;
            }
            var lines = new List<Line>();
            for (var i = 1; i < polygonVertices.Length; i++)
            {
                var line = new Line();
                var a = polygonVertices[i - 1];
                var b = polygonVertices[i];
                line.PointsCollection.Add(a);
                line.PointsCollection.Add(b);
                lines.Add(line);
            }
            var line2 = new Line();
            line2.PointsCollection.Add(polygonVertices[polygonVertices.Length - 1]);
            line2.PointsCollection.Add(polygonVertices[0]);
            lines.Add(line2);
            for (var i = 0; i < lines.Count; i++)
                for (var j = i + 2; j < lines.Count; j++)
                    if (Intersect(lines[i], lines[j]) && (i != 0 && j != lines.Count))
                        return true;
             
            return false;
        }

        /**
         * Dados 3 puntos respondemos
         * 1 si giran a contra reloj
         * -1 si giran con sentido reloj
         * 0 si son colineales
         */
        public static int Ccw(IPoint a, IPoint b, IPoint c)
        {
            double dx1, dx2, dy1, dy2;
            dx1 = b.X - a.X;
            dy1 = b.Y - a.Y;
            dx2 = c.X - a.X;
            dy2 = c.Y - a.Y;
            if (dx1 * dy2 > dy1 * dx2)
            {
                return +1;
            }
            if (dx1 * dy2 < dy1 * dx2)
            {
                return -1;
            }
            if ((dx1 * dx2 < 0) || (dy1 * dy2 < 0))
            {
                return -1;
            }
            if ((dx1 * dx1 + dy1 * dy1) < (dx2 * dx2 + dy2 * dy2))
            {
                return +1;
            }
            return 0;
        }

        /**
         * Dadas las lineas a y b calculamos si estas se intersecan
         */
        public static bool Intersect(Line a, Line b)
        {
            return ((Ccw(a.InitialPoint, a.FinalPoint, b.InitialPoint)
                    * Ccw(a.InitialPoint, a.FinalPoint, b.FinalPoint)) <= 0)
                    && ((Ccw(b.InitialPoint, b.FinalPoint, a.InitialPoint)
                    * Ccw(b.InitialPoint, b.FinalPoint, a.FinalPoint)) <= 0);
        }


    }
}




